
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stddef.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>


#define MODEM "/dev/ttyACM0"
#define BAUDRATE B9600    

struct termios tio;
int  tty_fd, flags;

int  arh_logged_in = 0;    // logged out
int  arh_logging   = 0;    // logging off
//int  arh_baudrate  = B9600;
//char arh_modem[24];
char res[512];
// Configuration parameters
char arh_url[80];
char arh_dev[80];
int  arh_id     =  7777;
int  arh_delay  = 12; // Number of 10sec between data report
int  connectToWebServer = 0;

//===============================
int toString(char a[]) {
  int c, sign, offset, n;
 
  if (a[0] == '-') {  // Handle negative integers
    sign = -1;
  }
 
  if (sign == -1) {  // Set starting position to convert
    offset = 1;
  }
  else {
    offset = 0;
  }
 
  n = 0;
 
  for (c = offset; a[c] != '\0'; c++) {
    n = n * 10 + a[c] - '0';
  }
 
  if (sign == -1) {
    n = -n;
  }
 
  return n;
}
//===============================
void readCom(char *p)
{
  FILE  *in;
  char  line[128];

  in = fopen("command.arh","r");
  if(in == NULL)
    {
      printf("Unable to open command.arh");
    }
  else
    {
      while (fgets(line,sizeof line,in) != NULL)
        {
          sscanf(line,"%s",p);
        }
    }
  fclose(in);
}
//===============================
void serverRequest(char res[], char msg[])
{
  // a = 97 read analog pin
  // d = 100 read digital pin
  // s = 115 set digital pin
  // w = 119 write analog pin pwm 0-255
  // p = 112 set pinMode

  unsigned char c='D';
  unsigned char z='D';
  int i,temp1,temp2;
            
  temp1  = (int)msg[1] - 48;
  temp2  = (int)msg[2] - 48;
  //printf("Send to Arduino server RS232/USB: command=%c  pin=%d value=%d\n",msg[0],temp1,temp2);
  for(i=0;i<3;i++)
    {
      z = msg[i];
      //printf("send %c ",z);
      write(tty_fd,&z,1);  // Write Serial data to Arduino
    }
  tcsetattr(tty_fd, TCSAFLUSH, &tio);
  //printf("Wait for server response\n[");
  int nn = 0;
  while (c != '.')
    {
      if (read(tty_fd,&c,1)>0) // Read Serial data from Arduino
        {
          //printf("%c",c);
          res[nn] = c;
          nn++;
        }
    }
  c = ' ';
  res[nn-1] = '\0';
  //printf("](%s)\n",res);      
  return;
}
//===============================
void delay(int t)
{
  t = t*1000; // convert to ms
  usleep(t);
}
//===============================
void oneWire(int dir,int steps)
{
  char command[4];
        
  dir = dir + 48;
  steps = steps + 48;
  command[0] = '{'; //123
  command[1] = 48;
  command[2] = 48;
  command[3] = '\0';
  serverRequest(res,command);
  return;
}
//===============================
void stepper(int dir,int steps)
{
  char command[4];
        
  dir = dir + 48;
  steps = steps + 48;
  command[0] = 'z';
  command[1] = (char)dir;
  command[2] = (char)steps;
  command[3] = '\0';
  serverRequest(res,command);
  return;
}
//===============================
int analogRead(int pin)
{
  char command[4];
        
  pin = pin + 48;
  command[0] = 'a';
  command[1] = (char)pin;
  command[2] = 48;
  command[3] = '\0';
  serverRequest(res,command);
  //int value = atoi(res[0])*100+atoi(res[1])*10+atoi(res[2]);
  return(atoi(res));
}
//===============================
int digitalRead(int pin)
{
  char command[4];
        
  pin = pin + 48;
  command[0] = 'd';
  command[1] = (char)pin;
  command[2] = 48;
  command[3] = '\0';
  serverRequest(res,command);
  return(atoi(res));
}
//===============================
void digitalWrite(int pin,int value)
{
  char command[4];
        
  pin = pin + 48;
  value = value + 48;
  command[0] = 's';
  command[1] = (char)pin;
  command[2] = (char)value;
  command[3] = '\0';
  serverRequest(res,command);
  return;
}
//===============================
void analogWrite(int pin,int value)
{
  char command[4];
        
  pin = pin + 48;
  value = value + 48;
  command[0] = 'w';
  command[1] = (char)pin;
  command[2] = (char)value;
  command[3] = '\0';
  serverRequest(res,command);
  return;
}
//===============================
void pinMode(int pin,int value)
{
  char command[4];
        
  pin = pin + 48;
  value = value + 48;
  command[0] = 'p';
  command[1] = (char)pin;
  command[2] = (char)value;
  command[3] = '\0';
  serverRequest(res,command);
  return;
}
//===============================
int readDDRD()
{
  char command[4];
  command[0] = 'A';
  command[1] = ' ';
  command[2] = ' ';
  command[3] = '\0';
  serverRequest(res,command);
  return(atoi(res));
}
//===============================
int readDDRB()
{
  char command[4];
  command[0] = 'B';
  command[1] = ' ';
  command[2] = ' ';
  command[3] = '\0';
  serverRequest(res,command);
  return(atoi(res));
}
//===============================
int readDDRC()
{
  char command[4];
  command[0] = 'C';
  command[1] = ' ';
  command[2] = ' ';
  command[3] = '\0';
  serverRequest(res,command);
  return(atoi(res));
}
//===============================
int readPORTD()
{
  char command[4];
  command[0] = 'D';
  command[1] = ' ';
  command[2] = ' ';
  command[3] = '\0';
  serverRequest(res,command);
  return(atoi(res));
}
//===============================
int readPORTB()
{
  char command[4];
  command[0] = 'E';
  command[1] = ' ';
  command[2] = ' ';
  command[3] = '\0';
  serverRequest(res,command);
  return(atoi(res));
}
//===============================
int readPORTC()
{
  char command[4];
  command[0] = 'F';
  command[1] = ' ';
  command[2] = ' ';
  command[3] = '\0';
  serverRequest(res,command);
  return(atoi(res));
}
//===============================
int readPIND()
{
  char command[4];
  command[0] = 'G';
  command[1] = ' ';
  command[2] = ' ';
  command[3] = '\0';
  serverRequest(res,command);
  return(atoi(res));
}
//===============================
int readPINB()
{
  char command[4];
  command[0] = 'H';
  command[1] = ' ';
  command[2] = ' ';
  command[3] = '\0';
  serverRequest(res,command);
  return(atoi(res));
}
//===============================
int readPINC()
{
  char command[4];
  command[0] = 'I';
  command[1] = ' ';
  command[2] = ' ';
  command[3] = '\0';
  serverRequest(res,command);
  return(atoi(res));
}
//===============================
char* readPinStatus()
{
  char command[4];
  command[0] = 'J';
  command[1] = ' ';
  command[2] = ' ';
  command[3] = '\0';
  serverRequest(res,command);
  return(res);
}

//===============================
void processArh()
//===============================
{
  FILE  *in;
  char  line[128];
  int i,com=0,pin=0,value=0;
   
  in = fopen("download.arh","r");
  if(in == NULL)
    {
      printf("Unable to open download.arh");
    }
  else
    {
      while (fgets(line,sizeof line,in) != NULL)
        {
          sscanf(line,"%d %d %d",&com,&pin,&value);
        }
      printf("INBOX: %s\n",line);
    }
  fclose(in);   
  system("rm -f download.arh");   


  if(com != 0)
    {
      if(com == 1) // welcome
        {
          connectToWebServer = 1;
          //printf("WebServer connection established %d \n",pin);
        }
      if(com == 2) // heartbeat response
        {
          printf("WebServer Heartbeat Response %d \n",pin);
        }
      if(com == 11) // login result
        {
          arh_logged_in = pin;
          if(pin==1)
            printf("ARH Logged In\n");
          else
            printf("ARH Logged Out\n");
        }
      if(com == 91) // delay
        {
          arh_delay = pin;
          printf("delay value=%d \n",arh_delay);
        }
      if(com == 92) // log on/off
        {
          arh_logging = pin;
          if(arh_logging == 1)
            printf("ARH logging ON\n");
          else
            printf("ARH logging OFF\n");
        }
      if(com == 115) // digitalWrite
        {
          digitalWrite(pin,value);
          //printf("digitalWrite pin=%d value=%d\n",pin,value);
        }
      if(com == 120) // digitalWrite all pins
        {
          for(i=2;i<=13;i++)digitalWrite(i,value);
          printf("all digitalWrite pin=%d value=%d\n",pin,value);
        }
      if(com == 121) // digitalWrite all pins
        {
          for(i=2;i<=13;i++)pinMode(i,value);
          printf("all pinMode pin=%d value=%d\n",pin,value);
        }
      if(com == 119) // analogWrite pwm
        {
          analogWrite(pin,value);
          //printf("analogWrite pin=%d value=%d\n",pin,value);
        }
      if(com == 112) // pinMode
        {
          pinMode(pin,value);
          //printf("pinMode pin=%d value=%d\n",pin,value);
        }
      if(com == 122) // stepper
        {
          stepper(pin,value); // pin= direction, value = steps
          printf("Stepper dir=%d steps=%d\n",pin,value);
        }
    }
}
//===============================
void readConfig()
//===============================
{
  FILE  *in,*out;
  char  line[128];
  char temps[12];

  in = fopen("config.arh","r");
  if(in == NULL)
    {
      printf("Create config file\n");
      out = fopen("config.arh","w");
      fprintf(out,"URL:      m2m.simuino.com/m2m.php\n");
      //fprintf(out,"DEVICE:   /dev/ttyACM0\n");
      fprintf(out,"DELAY:    12\n"); // 12 10sec
      fprintf(out,"IDENTITY: 9999\n"); 
      fclose(out);

      strcpy(arh_url,   "m2m.simuino.com/m2m.php");
      strcpy(arh_dev,   "/dev/ttyACM0");
      arh_id           = 9999;
      arh_delay        = 12; // Number of 10sec

    }
  else
    {
      printf("Open config file\n");
      while (fgets(line,sizeof line,in) != NULL)
          {
            if(strstr(line,"URL:") != NULL)sscanf(line,"%s %s",temps,arh_url);
            //if(strstr(line,"DEVICE:") != NULL)sscanf(line,"%s %s",temps,arh_dev);
            if(strstr(line,"DELAY:") != NULL)sscanf(line,"%s %d",temps,&arh_delay);
            if(strstr(line,"IDENTITY:") != NULL)sscanf(line,"%s %d",temps,&arh_id);
          }
      fclose(in);
    }
    
  
}
//===============================
void xreadDeviceName()
//===============================
{
  FILE  *in,*out;
  char  line[128];
  char temps[12];

  system("ls /dev | grep ACM > device.arh");
  
  in = fopen("device.arh","r");
  if(in == NULL)
    {
      printf("No device information file\n");
    }
  else
    {
      //printf("Open device file\n");
      while (fgets(line,sizeof line,in) != NULL)
        {
          if(strstr(line,"ttyACM") != NULL)sscanf(line,"%s",arh_dev);
        }
      fclose(in);
    }
}

//===============================
void readDeviceName()
//===============================
{
  FILE  *in,*out;
  char  line[128];
  char temps[12];

  system("ls /dev | grep ACM > device.arh");
  
  in = fopen("device.arh","r");
  if(in == NULL)
    {
      printf("No device information file\n");
    }
  else
    {
      //printf("Open device file\n");
      while (fgets(line,sizeof line,in) != NULL)
	{
	  if(strstr(line,"ttyACM") != NULL)sscanf(line,"%s",temps);
	  strcpy(arh_dev,"/dev/");
	  strcat(arh_dev,temps);
	}
      fclose(in);
    }
}
//===============================
void readIpAddress(char *ips)
//===============================
{
  FILE  *in;
  char  line[128];
  char  temps[12];
  int   net = 0,netType=0;

  system("ifconfig > ipaddress.arh");
  delay(1000);
  in = fopen("ipaddress.arh","r");
  printf("Open ip file\n");
  strcpy(ips,"no ip found");
  while (fgets(line,sizeof line,in) != NULL)
  { 
          if(strstr(line,"wlan") != NULL)
          {
             net = 1; //wlan
          }
          if(strstr(line,"eth") != NULL)
          {
             net = 2; //eth
          }
          if(strstr(line,"Loopback") != NULL)
          {
             net = 3; //lo
          }
          if(strstr(line,"inet addr:") != NULL)
          {
             if(net != 3)
             {
               netType = net;
               sscanf(line,"%s %s",temps,ips);
             }
          }
  }
  fclose(in);
  //printf("%d %s\n",netType,ips);
  return;
}
//===============================
int main(int argc,char** argv)
//===============================
{   
  int i,value = 9999;
  unsigned char c='D';
  unsigned char z='D';
  char res[120],com[120],sys[240],ip[80];
  int a0,a1,a2,a3,a4,a5,ddrd,ddrb,ddrc,portd,portb,portc,pind,pinb,pinc;
  int w1,w2,w3,w4,w5,oneWire=0,arh_ard=1;
    

  readConfig();
  readIpAddress(ip);


  printf("Device......: %s\n",arh_dev);
  //printf("BaudRate....: %d\n",arh_baudrate);
  printf("Id..........: %d\n",arh_id);
  printf("Delay.......: %d\n",arh_delay);
  printf("IP..........: %s\n",ip);

/*
  while(connectToWebServer == 0)
    {
      // Knock on WebServer door
      sprintf(sys,"wget -q -O download.arh \"http://m2m.simuino.com/m2m.php?hb=%d&id=%d&ard=%d&msg=10&ip=%s\"",arh_delay,arh_id,arh_ard,ip);
      printf("%s\n",sys);
      system(sys);
      processArh();
      delay(arh_delay);
    }

  while(arh_ard == 1)
    {
      memset(&tio,0,sizeof(tio));
      tio.c_iflag=0;
      tio.c_oflag=0;
      tio.c_cflag=CS8|CREAD|CLOCAL;  // 8n1, see termios.h for more information
      tio.c_lflag=0;
      tio.c_cc[VMIN]=1;
      tio.c_cc[VTIME]=5;
      if((tty_fd = open(arh_dev , O_RDWR | O_NONBLOCK)) == -1){
          printf("Waiting for Arduino connection...\n"); 
      // Inform WebServer about no connection to Arduino
      //sprintf(sys,"wget -q -O download.arh \"http://m2m.simuino.com/m2m.php?hb=%d&id=%d&ard=%d\"",arh_delay,arh_id,arh_ard);
          //printf("%s\n",sys);
          //system(sys);
      delay(10000);
        //exit(0);
      }
      else
        {
          arh_ard = 2;
      printf("Connected to Arduino %s\n",arh_dev); 
          cfsetospeed(&tio,BAUDRATE);    
          cfsetispeed(&tio,BAUDRATE);      

          tcsetattr(tty_fd,TCSANOW,&tio);
          tcsetattr(tty_fd, TCSAFLUSH, &tio);
          // Inform WebServer about connection to Arduino established
          sprintf(sys,"wget -q -O download.arh \"http://m2m.simuino.com/m2m.php?hb=%d&id=%d&ard=%d\"",arh_delay,arh_id,arh_ard);
          printf("%s\n",sys);
          system(sys);
        }
    } */
  int nn = 0;
    
  //==================================================
    
  int count=0;
  int m2m_state = 0;
  
  while(1)
    {
        
          if(m2m_state == 0) // Server connection
          {
                  printf("SERVER CONNECTION\n");
                  sprintf(sys,"wget -q -O download.arh \"http://m2m.simuino.com/m2m.php?hb=%d&id=%d&ard=%d&msg=10&ip=%s\"",arh_delay,arh_id,arh_ard,ip);
          //printf("%s\n",sys);
          system(sys);
          processArh();
          if(connectToWebServer == 1)m2m_state = 1;
          }
          if(m2m_state == 1) // Arduino present
          {
                  printf("ARDUINO PRESENT\n");
                  readDeviceName();
          if (strstr(arh_dev,"ttyACM") != NULL) m2m_state = 2;
          }
          if(m2m_state == 2) // Arduino connection
          {
                  printf("ARDUINO CONNECTION\n");
                  memset(&tio,0,sizeof(tio));
          tio.c_iflag=0;
          tio.c_oflag=0;
          tio.c_cflag=CS8|CREAD|CLOCAL;  // 8n1, see termios.h for more information
          tio.c_lflag=0;
          tio.c_cc[VMIN]=1;
          tio.c_cc[VTIME]=5;
          if((tty_fd = open(arh_dev , O_RDWR | O_NONBLOCK)) == -1){
                //printf("Waiting for Arduino connection...\n"); 
              }
          else
              {
                 arh_ard = 2;
             //printf("Connected to Arduino %s\n",arh_dev); 
                 cfsetospeed(&tio,BAUDRATE);    
                 cfsetispeed(&tio,BAUDRATE);      

                 tcsetattr(tty_fd,TCSANOW,&tio);
                 tcsetattr(tty_fd, TCSAFLUSH, &tio);
                 // Inform WebServer about connection to Arduino established
                 sprintf(sys,"wget -q -O download.arh \"http://m2m.simuino.com/m2m.php?hb=%d&id=%d&ard=%d\"",arh_delay,arh_id,arh_ard);
                 printf("%s\n",sys);
                 system(sys);
                 m2m_state = 3;
             }            
          }

          if(m2m_state == 3) // System up and running
          {
                printf("SYSTEM UP AND RUNNING\n");
        // Heartbeat to WebServer
        sprintf(sys,"wget -q -O download.arh \"http://m2m.simuino.com/m2m.php?hb=%d&id=%d&msg=11\"",arh_delay,arh_id);
        //printf("%s\n",sys);
        system(sys);
        processArh();

        if(count==arh_delay)
        {
          char *arh_status = readPinStatus();
          for(i=0;i<strlen(arh_status);i++)if(arh_status[i]=='+')arh_status[i]=' ';
          sscanf(arh_status,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",&a0,&a1,&a2,&a3,&a4,&a5,&ddrd,&ddrb,&ddrc,&portd,&portb,&portc,&pind,&pinb,&pinc,&oneWire,&w1,&w2,&w3,&w4,&w5);
          sprintf(sys,"wget -q -O download.arh \"http://m2m.simuino.com/m2m.php?id=%d&hb=%d&ard=%d&ddrd=%d&ddrb=%d&ddrc=%d&portd=%d&portb=%d&portc=%d&pind=%d&pinb=%d&pinc=%d&a0=%d&a1=%d&a2=%d&a3=%d&a4=%d&a5=%d&nw=%d&w1=%d&w2=%d&w3=%d&w4=%d&w5=%d\"",arh_id,arh_delay,arh_ard,ddrd,ddrb,ddrc,portd,portb,portc,pind,pinb,pinc,a0,a1,a2,a3,a4,a5,oneWire,w1,w2,w3,w4,w5);
          printf("%s\n",sys);
          system(sys);
          processArh();
          count = 0;
        }
        count++;
          }
        delay(10000); // Delay 10 seconds
    }
           
  close(tty_fd);
  return EXIT_SUCCESS;
}
